﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using ZoneLineNew.Attributes;
using ZoneLineNew.Core.Converters;

namespace ZoneLineNew.Controls {

    /// <summary>
    /// 自定义DataGrid控件
    /// </summary>
    public class DataGridPowerControl : DataGrid {

        public DataGridPowerControl() {

        }

        private IEnumerable _backValue;

        [Bindable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public IEnumerable ItemsSourceD {
            get { return (IEnumerable)GetValue(ItemsSourceDp); }
            set {
                if (value != _backValue) {
                    _backValue = value;
                    InitDataGrid(value);
                }
                SetValue(ItemsSourceDp, value);
            }
        }

        // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ItemsSourceDp =
            DependencyProperty.Register("ItemsSourceD", typeof(IEnumerable), typeof(DataGridPowerControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, IsBusyPropertyChanged));

        private static void IsBusyPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) {
            if (sender is DataGridPowerControl dgd) {
                dgd.ItemsSourceD = (IEnumerable)e.NewValue;
            }
        }

        public static Type GetElementType(IEnumerable enumerable) {
            if (enumerable == null) {
                return null;
            }
            // 如果enumerable是非泛型的IEnumerable，则直接返回Object类型
            if (enumerable is IEnumerable<object> ss) {
                return ss.FirstOrDefault()?.GetType();
            }

            // 如果enumerable是泛型的IEnumerable，尝试获取其泛型参数的类型
            Type enumerableType = enumerable.GetType();
            Type genericType = enumerableType.GetGenericArguments().FirstOrDefault();
            if (genericType != null) {
                return genericType;
            }

            // 如果上述都不成立，则尝试获取IEnumerable的第一个元素的类型
            var element = enumerable.Cast<object>().FirstOrDefault();
            return element?.GetType() ?? typeof(object);
        }

        private void InitDataGrid(IEnumerable value) {
            this.ItemsSource = null;
            var val = GetElementType(value);
            if (val != null) {
                var properties = val.GetProperties();

                List<DgColumnAttr> dgColumns = new List<DgColumnAttr>();

                foreach (var item in properties) {
                    var attrs = item.GetCustomAttributes(true);

                    foreach (var attr in attrs) {
                        IValueConverter converter = null;
                        if (attr is DgColumnConvertAttr converterAttr) {
                            converter = converterAttr.Converter;
                        }

                        if (attr is DgColumnAttr attrTemp) {
                            attrTemp.PropertyName = item.Name;
                            dgColumns.Add(attrTemp);
                            if (item.PropertyType == typeof(DateTime)) {
                                attrTemp.Converter = new TimeConverter();
                            } else if (converter != null) {
                                attrTemp.Converter = converter;
                            }
                        }
                    }
                }

                dgColumns = dgColumns.OrderBy(p => p.Index).ToList();

                this.Columns.Clear();

                foreach (var item in dgColumns) {
                    if (item.Converter != null) {
                        var column = new DataGridTextColumn() { Header = item.HeaderName, Binding = new Binding(item.PropertyName) { Converter = item.Converter } };
                        this.Columns.Add(column);
                    } else {
                        var column = new DataGridTextColumn() { Header = item.HeaderName, Binding = new Binding(item.PropertyName) };
                        this.Columns.Add(column);
                    }
                }

                this.ItemsSource = value;
            }

        }
    }

}
